#define _GNU_SOURCE
#include "app_serial.h"


/**
 * @brief 串口初始化
 *
 * @return int 0:成功 -1:失败
 */
int app_serial_init(device_t *device)
{
    int ret= app_serial_set_baud(device,BR_9600);
	if(ret==-1)
	{
		perror("app_serial_set_baud 错误");
		return -1;

	}
	 app_serial_set_parity(device,PARITY_NONE);
	 app_serial_set_stop(device,STOP_BIT_ONE);
	 app_serial_set_makeraw(device);

	 //要执行flush
	 ret= tcflush(device->dev_fd,TCIOFLUSH);
	 if(ret==-1)
	 {
		 perror("tcflush 错误");
		 return -1;
	 }
	 
	 return 0;
}



/**
 * @brief 波特率设置
 * @param baud 波特率
 * @return int 0:成功 -1:失败
 * //1 取出termios的结构体  
 * //2 设置值
 * //3 写入termios
 */
int app_serial_set_baud(device_t *device,SERIAL_BAUD_RATE baud)
{
	 //1 取出termios的结构体  
	 struct termios termios_attr;
	 int ret= tcgetattr( device->dev_fd, &termios_attr );
	 if(ret==-1)
	 {
		perror("tcgetattr 错误");
		return -1;
	 }
    //2 设置值
	cfsetspeed(&termios_attr,baud);
    //3 写入termios
	ret= tcsetattr( device->dev_fd, TCSAFLUSH, &termios_attr );
		 if(ret==-1)
	 {
		perror("tcsetattr 错误");
		return -1;
	 }
	 return 0;
}

/**
 * @brief 校验位设置
 * @param parity 校验位
 * @return int 0:成功 -1:失败
 */
int app_serial_set_parity(device_t *device,SERIAL_PARITY parity)
{
	//1 取出termios的结构体  
	 struct termios termios_attr;
	 int ret= tcgetattr( device->dev_fd, &termios_attr );
	 if(ret==-1)
	 {
		perror("tcgetattr 错误");
		return -1;
	 }
    //2 设置值
	 termios_attr.c_cflag &= ~(PARENB | PARODD); // 清除校验位、
     termios_attr.c_cflag |= parity;             // 设置校验位

    //3 写入termios
	ret= tcsetattr( device->dev_fd, TCSAFLUSH, &termios_attr );
		 if(ret==-1)
	 {
		perror("tcsetattr 错误");
		return -1;
	 }
	 return 0;
}

/**	
 * @brief 停止位设置
 * @param stop 停止位
 * @return int 0:成功 -1:失败
 */
int app_serial_set_stop(device_t *device,SERIAL_STOP_BIT stopbits)
{


	//1 取出termios的结构体  
	 struct termios termios_attr;
	 int ret= tcgetattr( device->dev_fd, &termios_attr );
	 if(ret==-1)
	 {
		perror("tcgetattr 错误");
		return -1;
	 }
    //2 设置值
    termios_attr.c_cflag &= ~CSTOPB;  // 清除停止位
    termios_attr.c_cflag |= stopbits; // 设置停止位


    //3 写入termios
	ret= tcsetattr( device->dev_fd, TCSAFLUSH, &termios_attr );
		 if(ret==-1)
	 {
		perror("tcsetattr 错误");
		return -1;
	 }
	 return 0;
}

/**
 * @brief 设置原始模式
 * @return int 0:成功 -1:失败
 */
int app_serial_set_makeraw(device_t *device)
{
	//1 取出termios的结构体  
	 struct termios termios_attr;
	 int ret= tcgetattr( device->dev_fd, &termios_attr );
	 if(ret==-1)
	 {
		perror("tcgetattr 错误");
		return -1;
	 }
    //2 设置值
	cfmakeraw(&termios_attr);


    //3 写入termios
	ret= tcsetattr( device->dev_fd, TCSAFLUSH, &termios_attr );
		 if(ret==-1)
	 {
		perror("tcsetattr 错误");
		return -1;
	 }
	 return 0;
}

/**
 * @brief 设置是否阻塞模式
 * @param block 是否阻塞模式 1:阻塞模式 0:非阻塞模式
 * @return int 0:成功 -1:失败
 */
int app_serial_set_block(device_t *device,int block)
{
//1 取出termios的结构体  
	 struct termios termios_attr;
	 int ret= tcgetattr( device->dev_fd, &termios_attr );
	 if(ret==-1)
	 {
		perror("tcgetattr 错误");
		return -1;
	 }
    //2 设置值
	//阻塞模式
	if(block)
	{	//日常接收数据使用
		termios_attr.c_cc[VTIME] = 0; //超时时间 0无限等待
		termios_attr.c_cc[VMIN] = 1;  //最小字符数 1
	}else
	{
		termios_attr.c_cc[VTIME] = 2; // 超时时间 每1= 100耗秒
		termios_attr.c_cc[VMIN] = 0;  //最小字符数 1
	}


    //3 写入termios
	ret= tcsetattr( device->dev_fd, TCSAFLUSH, &termios_attr );
		 if(ret==-1)
	 {
		perror("tcsetattr 错误");
		return -1;
	 }
	 return 0;
}